home *** CD-ROM | disk | FTP | other *** search
- Path: uunet!husc6!mit-eddie!uw-beaver!tektronix!tekgen!tekred!games-request
- From: games-request@tekred.TEK.COM
- Newsgroups: comp.sources.games
- Subject: v04i001: bog - the game of boggle
- Message-ID: <2273@tekred.TEK.COM>
- Date: 10 Mar 88 00:36:23 GMT
- Sender: billr@tekred.TEK.COM
- Lines: 2480
- Approved: billr@tekred.TEK.COM
-
- Submitted by: Barry Brachman <uunet!ubc-vision!cs.ubc.ca!brachman>
- Comp.sources.games: Volume 4, Issue 1
- Archive-name: bog
-
- [I compiled and ran this OK on a Sun 3/60. -br]
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of shell archive."
- # Contents: README Makefile bog.man bog.h bog.c help.c mach.c mkdict.c
- # mkindex.c prtable.c showdict.c timer.c word.c helpfile
- # Wrapped by billr@saab on Tue Mar 1 17:16:48 1988
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f README -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"README\"
- else
- echo shar: Extracting \"README\" \(2494 characters\)
- sed "s/^X//" >README <<'END_OF_README'
- X
- XBog is a fairly portable simulation of Parker Brother's game of Boggle and
- Xis similar to the 4.[23] BSD "boggle" and Sun's "boggletool".
- XBog has not been derived from any proprietary code.
- XIt has been tested on the Sun 3 under SunOS 3.2 and on the Atari 1040ST (MWC).
- X
- XWhat You Need
- X
- XYou will need curses/termcap and a large word list.
- XThe minix word list or /usr/dict/words will do nicely.
- XThe word list must already be sorted (you can use "sort -c" to check).
- X
- XContents
- X
- X README - this file
- X Makefile
- X bog.man - half-hearted man page (use the game's help command)
- X bog.h - configuration and header info
- X bog.c - machine independent game code
- X word.c - machine independent word list routines
- X help.c - (curses) help routine
- X mach.c - (curses) display code
- X prtable.c - ditto
- X timer.c - machine dependent (os) input polling
- X mkdict.c - convert a word list to a bog dictionary
- X mkindex.c - create an index file for the bog dictionary
- X showdict.c - print a bog dictionary to stdout
- X
- XPortability
- X
- X- I've tried to make bog.c (the program logic) independent of the I/O.
- X My plan was to make it straightforward to adapt the game to run under a
- X windowing system (eg., Suntools, GEM). I have no plan to actually do this.
- X I've stuck to a small subset of the curses routines.
- X- The program runs with the input in raw mode.
- X- If you want the running timer you must #define TIMER in bog.h
- X and insert the input polling code in timer.c for your system. There is
- X already code there for BSD, SYSV, and ATARI.
- X
- XSetup
- X
- X1. Check bog.h and Makefile and edit to fit your environment
- X2. "make all"
- X This will make all the binaries and create the dictionary and index files
- X3. Move "dict", "dict.ind", and "helpfile" to where you specified in bog.h
- X4. Play away
- X
- XDistribution
- X
- XYou may use this software for your enjoyment and you may share it with others.
- XYou may not sell this software or use it for any commercial purposes
- Xwhatsoever. All modified versions of the software that you redistribute must
- Xclearly indicate your changes.
- X
- XIf you come across any bugs or make any changes you'd like to share please
- Xsend mail to me rather than posting to the net.
- X
- XEnjoy. [But beware: boggle can be addictive!]
- X
- X-----
- XBarry Brachman | {ihnp4!alberta,uw-beaver,uunet}!
- XDept. of Computer Science| ubc-vision!ubc-csgrads!brachman
- XUniv. of British Columbia| brachman@grads.cs.ubc.cdn
- XVancouver, B.C. V6T 1W5 | brachman%ubc.csnet@csnet-relay.arpa
- X(604) 228-4327 | brachman@ubc.csnet
- X
- END_OF_README
- if test 2494 -ne `wc -c <README`; then
- echo shar: \"README\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f Makefile -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"Makefile\"
- else
- echo shar: Extracting \"Makefile\" \(830 characters\)
- sed "s/^X//" >Makefile <<'END_OF_Makefile'
- X
- X# See bog.h for configuration
- X
- XOBJS=bog.o help.o mach.o prtable.o timer.o word.o
- X
- XCFLAGS=-O
- XLIBS=-lcurses -ltermlib
- X
- X# DICT is the dictionary that will be used to construct the word list used
- X# by bog
- XDICT=/usr/dict/words
- X
- Xbog: $(OBJS)
- X cc $(CFLAGS) -s -o bog $(OBJS) $(LIBS)
- X
- Xall: bog mkdict mkindex dict
- X
- Xmkdict: mkdict.c
- X cc -s -O -o mkdict mkdict.c
- X
- Xmkindex: mkindex.c
- X cc -s -O -o mkindex mkindex.c
- X
- Xshowdict: showdict.o word.o
- X cc -s -O -o showdict showdict.o word.o
- X rm -f showdict.o
- X
- Xdict: mkdict mkindex
- X ./mkdict < $(DICT) > dict
- X ./mkindex < dict > dict.ind
- X
- X$(OBJS): bog.h
- X
- Xinstall: all
- X @echo "Move dict, dict.ind, and the helpfile to where you specified in bog.h"
- X @echo "Move bog.man to where you want the manual page to go"
- X
- Xclean:
- X rm -f *.o bog
- X
- Xlint:
- X lint -abchx bog.c help.c mach.c prtable.c timer.c word.c
- X
- END_OF_Makefile
- if test 830 -ne `wc -c <Makefile`; then
- echo shar: \"Makefile\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f bog.man -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"bog.man\"
- else
- echo shar: Extracting \"bog.man\" \(2748 characters\)
- sed "s/^X//" >bog.man <<'END_OF_bog.man'
- X.TH BOG 1-LOCAL "22 February 1988"
- X.UC
- X.SH NAME
- Xbog \- Word search game
- X.SH SYNOPSIS
- Xbog [-b] [-d] [-s#] [-t#] [-w#] [+[+]] [boardspec]
- X.br
- Xmkdict
- X.br
- Xmkindex
- X.SH DESCRIPTION
- XThe object of
- X.I bog
- Xis to find as many words as possible on the Boggle board within the three
- Xminute time limit.
- XA Boggle board is a four by four arrangement of Boggle cubes, each side of
- Xeach cube displaying a letter of the alphabet or `qu'.
- XWords are formed by finding a sequence of cubes (letters) that are in the
- Xgame's dictionary.
- XThe (N+1)th cube in the word must be horizontally,
- Xvertically, or diagonally adjacent to the Nth cube.
- XCubes cannot be reused.
- XWords consist solely of lower case letters and must be at least 3 letters long.
- X.PP
- XCommand line flags can be given to change the rules of the game.
- XThe
- X.B +
- Xflag allows a cube to be used multiple times, but not in succession.
- XThe
- X.B ++
- Xflag allows the same cubes to be considered adjacent to itself.
- X.B
- XA seed other than the time of day is specified by
- X.B -s#,
- Xwhere
- X.B #
- Xis the seed.
- XThe time limit can be changed from the default 3 minutes by using the flag
- X.B -t#,
- Xwhere
- X.B #
- Xis the duration (in seconds) of each game.
- XThe minimum word length can be changed from 3 letters by specifying
- X.B -w#,
- Xwhere
- X.B #
- Xis the minimum number of letters to use.
- X.PP
- XA starting board position can be specified on the command line by
- Xlisting the board left to right and top to bottom.
- X.PP
- XThe
- X.B -b
- Xflag puts
- X.I bog
- Xin batch mode.
- XA
- X.B boardspec
- Xmust also be given.
- XThe dictionary is read from stdin and a list of words appearing in
- X.B boardspec
- Xis printed to stdout.
- X.PP
- XHelp is available during play by typing `?'.
- XMore detailed information on the game is given there.
- X.PP
- X.I Mkdict
- Xreads a word list from stdin, one word per line, and writes a dictionary
- Xusable by
- X.I bog
- Xto stdout.
- XThe dictionary is assumed to be sorted.
- XImproper words are filtered out.
- X.PP
- X.I Mkindex
- Xreads a dictionary produced by
- X.I mkdict
- Xfrom stdin
- Xand writes an index file usable by
- X.I bog
- Xto stdout.
- X.SH FILES
- X.I Bog
- Xaccesses a dictionary file, a dictionary index file, and a helpfile.
- XLocations are system dependent.
- XThe dictionary file must have been created by
- X.I mkdict
- Xand the index file by
- X.I mkindex.
- X.SH SEE ALSO
- Xboggle(6), boggletool(6)
- X.SH BUGS
- XIf there are a great many words in the cube the final display of the words
- Xmay scroll off of the screen. (On a 25 line screen about 130 words can be
- Xdisplayed.)
- X.sp 2
- XNo word can contain a 'q' that is not immediately followed by a 'u'.
- X.sp 2
- XWhen using the '+' or '++' options the display of words found in the board
- Xdoesn't indicate reused cubes.
- X.SH AUTHOR
- XBoggle is a trademark of Parker Brothers.
- X.sp 2
- XBarry Brachman
- X.br
- XDept. of Computer Science
- X.br
- XUniversity of British Columbia
- END_OF_bog.man
- if test 2748 -ne `wc -c <bog.man`; then
- echo shar: \"bog.man\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f bog.h -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"bog.h\"
- else
- echo shar: Extracting \"bog.h\" \(1177 characters\)
- sed "s/^X//" >bog.h <<'END_OF_bog.h'
- X/* vi: set tabstop=4 : */
- X
- X/*
- X * Configuration
- X */
- X
- X#define BSD42 1 /* BSD 4.[23] */
- X/* #define ATARI 1 /* Atari ST */
- X/* #define SYSV 1 /* System V */
- X
- X/*
- X * If you don't have random() and srandom() #define what you have
- X */
- X/* #define random lrand48 /* Sys V */
- X/* #define srandom srand48 /* Sys V */
- X
- X/* #define random rand /* Not good but generally available */
- X/* #define srandom(x) srand((int) x) /* */
- X
- X#define TIMER 1 /* Use tty polling (see timer.c) */
- X#define LOADDICT 1 /* Load the dictionary for speed */
- X
- X#define DICT "/usr/cna/billr/games/bog/dict"
- X#define DICTINDEX "/usr/cna/billr/games/bog/dict.ind"
- X#define HELPFILE "/usr/cna/billr/games/bog/helpfile"
- X
- X/*
- X * The theoretical maximum for MAXWORDLEN is ('a' - 1) == 96
- X */
- X#define MAXWORDLEN 40
- X#define MAXPWORDS 200
- X#define MAXMWORDS 200
- X#define MAXPSPACE 2000
- X#define MAXMSPACE 4000
- X
- X#define MAXCOLS 20
- X
- X#define PROMPT_COL 20
- X#define PROMPT_LINE 2
- X
- X#define BOARD_COL 0
- X#define BOARD_LINE 0
- X
- X#define SCORE_COL 20
- X#define SCORE_LINE 0
- X
- X#define LIST_COL 0
- X#define LIST_LINE 10
- X
- X#define TIMER_COL 20
- X#define TIMER_LINE 2
- X
- Xstruct dictindex {
- X long start;
- X long length;
- X};
- X
- END_OF_bog.h
- if test 1177 -ne `wc -c <bog.h`; then
- echo shar: \"bog.h\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f bog.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"bog.c\"
- else
- echo shar: Extracting \"bog.c\" \(13598 characters\)
- sed "s/^X//" >bog.c <<'END_OF_bog.c'
- X/* vi: set tabstop=4 : */
- X
- X#include "bog.h"
- X
- X#include <ctype.h>
- X#include <stdio.h>
- X
- Xchar *version[] = "bog V1.0 brachman@ubc.csnet 23-Feb-88";
- X
- Xstruct dictindex dictindex[26];
- X
- X/*
- X * Cube position numbering:
- X *
- X * 0 1 2 3
- X * 4 5 6 7
- X * 8 9 A B
- X * C D E F
- X */
- Xstatic int adjacency[16][16] = {
- X/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
- X { 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* 0 */
- X { 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* 1 */
- X { 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 }, /* 2 */
- X { 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 }, /* 3 */
- X { 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0 }, /* 4 */
- X { 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0 }, /* 5 */
- X { 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0 }, /* 6 */
- X { 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0 }, /* 7 */
- X { 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0 }, /* 8 */
- X { 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0 }, /* 9 */
- X { 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1 }, /* A */
- X { 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1 }, /* B */
- X { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0 }, /* C */
- X { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0 }, /* D */
- X { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1 }, /* E */
- X { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0 } /* F */
- X};
- X
- Xstatic int letter_map[26][16];
- X
- Xchar board[17];
- Xint wordpath[MAXWORDLEN + 1];
- Xint wordlen; /* Length of last word returned by nextword() */
- Xint usedbits;
- X
- Xchar *pword[MAXPWORDS], pwords[MAXPSPACE], *pwordsp;
- Xint npwords;
- X
- Xchar *mword[MAXMWORDS], mwords[MAXMSPACE], *mwordsp;
- Xint nmwords;
- X
- Xint ngames = 0;
- Xint tnmwords = 0, tnpwords = 0;
- X
- X#ifdef TIMER
- X#include <setjmp.h>
- X
- Xjmp_buf env;
- X#endif TIMER
- X
- Xlong start_t;
- X
- Xstatic FILE *dictfp = (FILE *) NULL;
- X
- Xint batch;
- Xint debug;
- Xint minlength;
- Xint reuse;
- Xint tlimit;
- X
- Xchar *batchword(), *getline();
- X
- Xmain(argc, argv)
- Xint argc;
- Xchar **argv;
- X{
- X int done, i, selfuse;
- X char *bspec, *p;
- X long t;
- X long atol();
- X FILE *opendict();
- X
- X debug = 0;
- X bspec = (char *) NULL;
- X reuse = 0;
- X batch = 0;
- X selfuse = 0;
- X minlength = 3;
- X tlimit = 180; /* 3 minutes is standard */
- X time(&t);
- X
- X for (i = 1; i < argc; i++) {
- X if (argv[i][0] == '-') {
- X switch (argv[i][1]) {
- X case 'b':
- X batch = 1;
- X break;
- X case 'd':
- X debug = 1;
- X break;
- X case 's':
- X t = atol(&argv[i][2]);
- X break;
- X case 't':
- X if ((tlimit = atoi(&argv[i][2])) < 1) {
- X (void) fprintf(stderr, "Bad time limit\n");
- X exit(1);
- X }
- X break;
- X case 'w':
- X if ((minlength = atoi(&argv[i][2])) < 3) {
- X (void) fprintf(stderr, "Min word length must be > 2\n");
- X exit(1);
- X }
- X break;
- X default:
- X usage();
- X /*NOTREACHED*/
- X }
- X }
- X else if (strcmp(argv[i], "+") == 0)
- X reuse = 1;
- X else if (strcmp(argv[i], "++") == 0)
- X selfuse = 1;
- X else if (islower(argv[i][0])) {
- X if (strlen(argv[i]) != 16) {
- X usage();
- X /*NOTREACHED*/
- X }
- X /* This board is assumed to be valid... */
- X bspec = argv[i];
- X }
- X else {
- X usage();
- X /*NOREACHED*/
- X }
- X }
- X
- X if (batch && bspec == (char *) NULL) {
- X (void) fprintf(stderr, "Must give both -b and a board setup\n");
- X exit(1);
- X }
- X
- X if (selfuse) {
- X for (i = 0; i < 16; i++)
- X adjacency[i][i] = 1;
- X }
- X
- X if (batch) {
- X newgame(bspec);
- X while ((p = batchword(stdin)) != (char *) NULL)
- X (void) printf("%s\n", p);
- X }
- X else {
- X if (debug)
- X (void) printf("seed = %ld\n", t);
- X setup();
- X prompt("Loading the dictionary...");
- X if ((dictfp = opendict(DICT)) == (FILE *) NULL) {
- X (void) fprintf(stderr, "Can't load %s\n", DICT);
- X cleanup();
- X exit(1);
- X }
- X#ifdef LOADDICT
- X if (loaddict(dictfp) < 0) {
- X (void) fprintf(stderr, "Can't load %s\n", DICT);
- X cleanup();
- X exit(1);
- X }
- X (void) fclose(dictfp);
- X dictfp = (FILE *) NULL;
- X#endif
- X if (loadindex(DICTINDEX) < 0) {
- X (void) fprintf(stderr, "Can't load %s\n", DICTINDEX);
- X cleanup();
- X exit(1);
- X }
- X srandom(t);
- X
- X prompt("Type <space> to begin...");
- X while (inputch() != ' ')
- X ;
- X
- X done = 0;
- X while (!done) {
- X newgame(bspec);
- X bspec = (char *) NULL; /* reset for subsequent games */
- X playgame();
- X prompt("Type <space> to continue, any cap to quit...");
- X flushin(stdin);
- X while (1) {
- X int ch;
- X
- X ch = inputch();
- X if (ch == '\033')
- X findword();
- X else {
- X if (isupper(ch)) {
- X done = 1;
- X break;
- X }
- X if (ch == ' ')
- X break;
- X }
- X }
- X }
- X cleanup();
- X }
- X exit(0);
- X}
- X
- X/*
- X * Read a line from the given stream and check if it is legal
- X * Return a pointer to a legal word or a null pointer when EOF is reached
- X */
- Xchar *
- Xbatchword(fp)
- XFILE *fp;
- X{
- X register int *p, *q;
- X register char *w;
- X char *nextword();
- X
- X q = &wordpath[MAXWORDLEN + 1];
- X p = wordpath;
- X while (p < q)
- X *p++ = -1;
- X while ((w = nextword(fp)) != (char *) NULL) {
- X if (wordlen < minlength)
- X continue;
- X p = wordpath;
- X while (p < q && *p != -1)
- X *p++ = -1;
- X usedbits = 0;
- X if (checkword(w, -1, wordpath) != -1)
- X return(w);
- X }
- X return((char *) NULL);
- X}
- X
- X/*
- X * Play a single game
- X * Reset the word lists from last game
- X * Keep track of the running stats
- X */
- Xplaygame()
- X{
- X /* Can't use register variables if setjmp() is used! */
- X int i, *p, *q;
- X long t;
- X char buf[MAXWORDLEN + 1];
- X int compar();
- X
- X ngames++;
- X npwords = 0;
- X pwordsp = pwords;
- X nmwords = 0;
- X mwordsp = mwords;
- X
- X time(&start_t);
- X
- X q = &wordpath[MAXWORDLEN + 1];
- X p = wordpath;
- X while (p < q)
- X *p++ = -1;
- X showboard(board);
- X startwords();
- X if (setjmp(env)) {
- X badword();
- X goto timesup;
- X }
- X
- X while (1) {
- X if (getline(buf) == (char *) NULL) {
- X if (feof(stdin))
- X clearerr(stdin);
- X break;
- X }
- X time(&t);
- X if (t - start_t >= tlimit) {
- X badword();
- X break;
- X }
- X if (buf[0] == '\0') {
- X int remaining;
- X
- X remaining = tlimit - (int) (t - start_t);
- X (void) sprintf(buf, "%d:%02d", remaining / 60, remaining % 60);
- X showstr(buf, 1);
- X continue;
- X }
- X if (strlen(buf) < minlength) {
- X badword();
- X continue;
- X }
- X
- X p = wordpath;
- X while (p < q && *p != -1)
- X *p++ = -1;
- X usedbits = 0;
- X
- X if (checkword(buf, -1, wordpath) < 0)
- X badword();
- X else {
- X if (debug) {
- X (void) printf("[");
- X for (i = 0; wordpath[i] != -1; i++)
- X (void) printf(" %d", wordpath[i]);
- X (void) printf(" ]\n");
- X }
- X for (i = 0; i < npwords; i++) {
- X if (strcmp(pword[i], buf) == 0)
- X break;
- X }
- X if (i != npwords) { /* already used the word */
- X badword();
- X showword(i);
- X }
- X else if (!validword(buf))
- X badword();
- X else {
- X int len;
- X
- X len = strlen(buf) + 1;
- X if (npwords == MAXPWORDS - 1 ||
- X pwordsp + len >= &pwords[MAXPSPACE]) {
- X (void) fprintf(stderr, "Too many words!\n");
- X cleanup();
- X exit(1);
- X }
- X pword[npwords++] = pwordsp;
- X (void) strcpy(pwordsp, buf);
- X pwordsp += len;
- X addword(buf);
- X }
- X }
- X }
- X
- Xtimesup: ;
- X
- X /*
- X * Sort the player's words and terminate the list with a null
- X * entry to help out checkdict()
- X */
- X qsort(pword, npwords, sizeof(pword[0]), compar);
- X pword[npwords] = (char *) NULL;
- X
- X /*
- X * These words don't need to be sorted since the dictionary is sorted
- X */
- X checkdict();
- X
- X tnmwords += nmwords;
- X tnpwords += npwords;
- X
- X results();
- X}
- X
- X/*
- X * Check if the given word is present on the board, with the constraint
- X * that the first letter of the word is adjacent to square 'prev'
- X * Keep track of the current path of squares for the word
- X * A 'q' must be followed by a 'u'
- X * Words must end with a null
- X * Return 1 on success, -1 on failure
- X */
- Xcheckword(word, prev, path)
- Xchar *word;
- Xint prev, *path;
- X{
- X register char *p, *q;
- X register int i, *lm;
- X
- X if (debug) {
- X (void) printf("checkword(%s, %d, [", word, prev);
- X for (i = 0; wordpath[i] != -1; i++)
- X (void) printf(" %d", wordpath[i]);
- X (void) printf(" ]\n");
- X }
- X
- X if (*word == '\0')
- X return(1);
- X
- X lm = letter_map[*word - 'a'];
- X
- X if (prev == -1) {
- X char subword[MAXWORDLEN + 1];
- X
- X /*
- X * Check for letters not appearing in the cube to eliminate some
- X * recursive calls
- X * Fold 'qu' into 'q'
- X */
- X p = word;
- X q = subword;
- X while (*p != '\0') {
- X if (*letter_map[*p - 'a'] == -1)
- X return(-1);
- X *q++ = *p;
- X if (*p++ == 'q') {
- X if (*p++ != 'u')
- X return(-1);
- X }
- X }
- X *q = '\0';
- X while (*lm != -1) {
- X *path = *lm;
- X usedbits |= (1 << *lm);
- X if (checkword(subword + 1, *lm, path + 1) > 0)
- X return(1);
- X usedbits &= ~(1 << *lm);
- X lm++;
- X }
- X return(-1);
- X }
- X
- X /*
- X * A cube is only adjacent to itself in the adjacency matrix if selfuse
- X * was set, so a cube can't be used twice in succession if only the reuse
- X * flag is set
- X */
- X for (i = 0; lm[i] != -1; i++) {
- X if (adjacency[prev][lm[i]]) {
- X int used;
- X
- X used = 1 << lm[i];
- X /* If necessary, check if the square has already been used */
- X if (!reuse && (usedbits & used))
- X continue;
- X *path = lm[i];
- X usedbits |= used;
- X if (checkword(word + 1, lm[i], path + 1) > 0)
- X return(1);
- X usedbits &= ~used;
- X }
- X }
- X *path = -1; /* in case of a backtrack */
- X return(-1);
- X}
- X
- X/*
- X * A word is invalid if it is not in the dictionary
- X * At this point it is already known that the word can be formed from
- X * the current board
- X */
- Xvalidword(word)
- Xchar *word;
- X{
- X register int j;
- X register char *q, *w;
- X char *nextword();
- X
- X j = word[0] - 'a';
- X if (dictseek(dictfp, dictindex[j].start, 0) < 0) {
- X (void) fprintf(stderr, "Seek error\n");
- X cleanup();
- X exit(1);
- X }
- X
- X while ((w = nextword(dictfp)) != (char *) NULL) {
- X int ch;
- X
- X if (*w != word[0]) /* end of words starting with word[0] */
- X break;
- X q = word;
- X while ((ch = *w++) == *q++ && ch != '\0')
- X ;
- X if (*(w - 1) == '\0' && *(q - 1) == '\0')
- X return(1);
- X }
- X if (dictfp != (FILE *) NULL && feof(dictfp)) /* Special case for z's */
- X clearerr(dictfp);
- X return(0);
- X}
- X
- X/*
- X * Check each word in the dictionary against the board
- X * Delete words from the machine list that the player has found
- X * Assume both the dictionary and the player's words are already sorted
- X */
- Xcheckdict()
- X{
- X register char *p, **pw, *w;
- X register int i;
- X int prevch, previndex, *pi, *qi, st;
- X
- X mwordsp = mwords;
- X nmwords = 0;
- X pw = pword;
- X prevch ='a';
- X qi = &wordpath[MAXWORDLEN + 1];
- X
- X (void) dictseek(dictfp, 0L, 0);
- X while ((w = nextword(dictfp)) != (char *) NULL) {
- X if (wordlen < minlength)
- X continue;
- X if (*w != prevch) {
- X /*
- X * If we've moved on to a word with a different first letter
- X * then we can speed things up by skipping all words starting
- X * with a letter that doesn't appear in the cube
- X */
- X i = (int) (*w - 'a');
- X while (i < 26 && letter_map[i][0] == -1)
- X i++;
- X if (i == 26)
- X break;
- X previndex = prevch - 'a';
- X prevch = i + 'a';
- X /*
- X * Fall through if the word's first letter appears in the cube
- X * (i.e., if we can't skip ahead), otherwise seek to the
- X * beginning of words in the dictionary starting with the
- X * next letter (alphabetically) appearing in the cube and then
- X * read the first word
- X */
- X if (i != previndex + 1) {
- X if (dictseek(dictfp, dictindex[i].start, 0) < 0) {
- X (void) fprintf(stderr, "Seek error in checkdict()\n");
- X cleanup();
- X exit(1);
- X }
- X continue;
- X }
- X }
- X
- X pi = wordpath;
- X while (pi < qi && *pi != -1)
- X *pi++ = -1;
- X usedbits = 0;
- X if (checkword(w, -1, wordpath) == -1)
- X continue;
- X
- X st = 1;
- X while (*pw != (char *) NULL && (st = strcmp(*pw, w)) < 0)
- X pw++;
- X if (st == 0) /* found it */
- X continue;
- X if (nmwords == MAXMWORDS ||
- X mwordsp + wordlen + 1 >= &mwords[MAXMSPACE]) {
- X (void) fprintf(stderr, "Too many words!\n");
- X cleanup();
- X exit(1);
- X }
- X mword[nmwords++] = mwordsp;
- X p = w;
- X while (*mwordsp++ = *p++)
- X ;
- X }
- X}
- X
- X/*
- X * Crank up a new game
- X * If the argument is non-null then it is assumed to be a legal board spec
- X * in ascending cube order, oth. make a random board
- X */
- Xnewgame(b)
- Xchar *b;
- X{
- X register int i, p, q;
- X char *tmp;
- X int *lm[26];
- X long random();
- X static char *cubes[16] = {
- X "ednosw", "aaciot", "acelrs", "ehinps",
- X "eefhiy", "elpstu", "acdemp", "gilruw",
- X "egkluy", "ahmors", "abilty", "adenvz",
- X "bfiorx", "dknotu", "abjmoq", "egintv"
- X };
- X
- X if (b == (char *) NULL) {
- X /*
- X * Shake the cubes and make the board
- X */
- X i = 0;
- X while (i < 100) {
- X p = (int) (random() % 16);
- X q = (int) (random() % 16);
- X if (p != q) {
- X tmp = cubes[p];
- X cubes[p] = cubes[q];
- X cubes[q] = tmp;
- X i++;
- X }
- X /* else try again */
- X }
- X
- X for (i = 0; i < 16; i++)
- X board[i] = cubes[i][random() % 6];
- X }
- X else {
- X for (i = 0; i < 16; i++)
- X board[i] = b[i];
- X }
- X board[16] = '\0';
- X
- X /*
- X * Set up the map from letter to location(s)
- X * Each list is terminated by a -1 entry
- X */
- X for (i = 0; i < 26; i++) {
- X lm[i] = letter_map[i];
- X *lm[i] = -1;
- X }
- X
- X for (i = 0; i < 16; i++) {
- X register int j;
- X
- X j = (int) (board[i] - 'a');
- X *lm[j] = i;
- X *(++lm[j]) = -1;
- X }
- X
- X if (debug) {
- X for (i = 0; i < 26; i++) {
- X int ch, j;
- X
- X (void) printf("%c:", 'a' + i);
- X for (j = 0; (ch = letter_map[i][j]) != -1; j++)
- X (void) printf(" %d", ch);
- X (void) printf("\n");
- X }
- X }
- X
- X}
- X
- Xcompar(p, q)
- Xchar **p, **q;
- X{
- X return(strcmp(*p, *q));
- X}
- X
- Xusage()
- X{
- X(void) fprintf(stderr,
- X"Usage: bog [-b] [-d] [-s#] [-t#] [-w#] [+[+]] [boardspec]\n");
- X(void) fprintf(stderr, "-b: 'batch mode' (boardspec must be present)\n");
- X(void) fprintf(stderr, "-d: debug\n");
- X(void) fprintf(stderr, "-s#: use # as the random number seed\n");
- X(void) fprintf(stderr, "-t#: time limit is # seconds\n");
- X(void) fprintf(stderr, "-w#: minimum word length is # letters\n");
- X(void) fprintf(stderr, "+: can reuse a cube, but not twice in succession\n");
- X(void) fprintf(stderr, "++: can reuse cubes arbitrarily\n");
- X(void) fprintf(stderr, "boardspec: the first board to use (use 'q' for 'qu')\n");
- X exit(1);
- X}
- X
- END_OF_bog.c
- if test 13598 -ne `wc -c <bog.c`; then
- echo shar: \"bog.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f help.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"help.c\"
- else
- echo shar: Extracting \"help.c\" \(1149 characters\)
- sed "s/^X//" >help.c <<'END_OF_help.c'
- X/* vi: set tabstop=4 : */
- X
- X#include <curses.h>
- X#include <stdio.h>
- X
- X#include "bog.h"
- X
- Xhelp()
- X{
- X int eof, i;
- X FILE *fp;
- X WINDOW *win;
- X char buf[BUFSIZ];
- X extern int ncols, nlines;
- X
- X if ((fp = fopen(HELPFILE, "r")) == (FILE *) NULL)
- X return(-1);
- X win = newwin(0, 0, 0, 0);
- X clearok(win, 1);
- X
- X eof = 0;
- X if (ungetc(getc(fp), fp) == EOF) {
- X wprintw(win, "There doesn't seem to be any help.");
- X eof = 1; /* Nothing there... */
- X }
- X
- X while (!eof) {
- X for (i = 0; i < nlines - 3; i++) {
- X if (fgets(buf, sizeof(buf), fp) == (char *) NULL) {
- X eof = 1;
- X break;
- X }
- X if (buf[0] == '.' && buf[1] == '\n')
- X break;
- X wprintw(win, "%s", buf);
- X }
- X if (eof || ungetc(getc(fp), fp) == EOF) {
- X eof = 1;
- X break;
- X }
- X wmove(win, nlines - 1, 0);
- X wprintw(win, "Type <space> to continue, anything else to quit...");
- X wrefresh(win);
- X if ((inputch() & 0177) != ' ')
- X break;
- X wclear(win);
- X }
- X
- X fclose(fp);
- X if (eof) {
- X extern char *version;
- X
- X wprintw(win, "%s", version);
- X wmove(win, nlines - 1, 0);
- X wprintw(win, "Hit any key to continue...");
- X wrefresh(win);
- X inputch();
- X }
- X delwin(win);
- X clearok(stdscr, 1);
- X refresh();
- X return(0);
- X}
- X
- END_OF_help.c
- if test 1149 -ne `wc -c <help.c`; then
- echo shar: \"help.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f mach.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"mach.c\"
- else
- echo shar: Extracting \"mach.c\" \(10502 characters\)
- sed "s/^X//" >mach.c <<'END_OF_mach.c'
- X/* vi: set tabstop=4 : */
- X
- X/*
- X * Terminal interface
- X *
- X * Input is raw and unechoed
- X */
- X
- X#ifdef unix
- X#include <sgtty.h>
- X#endif
- X#include <signal.h>
- X#include <curses.h>
- X#include <ctype.h>
- X#include <stdio.h>
- X
- X#include "bog.h"
- X
- Xstatic int ccol, crow, maxw;
- Xstatic int colstarts[MAXCOLS], ncolstarts;
- Xstatic int lastline;
- Xint ncols, nlines;
- X
- X/*
- X * Do system dependent initialization
- X * This is called once, when the program starts
- X */
- Xsetup()
- X{
- X
- X if (tty_setup() < 0)
- X return(-1);
- X return(0);
- X}
- X
- X/*
- X * Do system dependent clean up
- X * This is called once, just before the program terminates
- X */
- Xcleanup()
- X{
- X
- X tty_cleanup();
- X}
- X
- X/*
- X * Display the player's word list, the list of words not found, and the running
- X * stats
- X */
- Xresults()
- X{
- X int col, row;
- X int denom1, denom2;
- X extern int ngames, nmwords, npwords, tnmwords, tnpwords;
- X extern char *pword[], *mword[];
- X int prwidth(), prword();
- X
- X move(LIST_LINE, LIST_COL);
- X clrtobot();
- X printw("Words you found (%d):", npwords);
- X refresh();
- X move(LIST_LINE + 1, LIST_COL);
- X prtable(pword, npwords, 0, ncols, prword, prwidth);
- X
- X getyx(stdscr, row, col);
- X move(row + 1, col);
- X printw("Words you missed (%d):", nmwords);
- X refresh();
- X move(row + 2, col);
- X prtable(mword, nmwords, 0, ncols, prword, prwidth);
- X
- X denom1 = npwords + nmwords;
- X denom2 = tnpwords + tnmwords;
- X
- X move(SCORE_LINE, SCORE_COL);
- X printw("Percentage: %0.2f%% (%0.2f%% over %d game%s)\n",
- X denom1 ? (100.0 * npwords) / (double) (npwords + nmwords) : 0.0,
- X denom2 ? (100.0 * tnpwords) / (double) (tnpwords + tnmwords) : 0.0,
- X ngames, ngames > 1 ? "s" : "");
- X}
- X
- Xstatic
- Xprword(base, index)
- Xchar **base;
- Xint index;
- X{
- X
- X printw("%s", base[index]);
- X}
- X
- Xstatic
- Xprwidth(base, index)
- Xchar **base;
- Xint index;
- X{
- X
- X return(strlen(base[index]));
- X}
- X
- X/*
- X * Main input routine
- X *
- X * - doesn't accept words longer than MAXWORDLEN or containing caps
- X */
- Xchar *
- Xgetline(q)
- Xchar *q;
- X{
- X register int ch, done;
- X register char *p;
- X int row, col;
- X
- X p = q;
- X done = 0;
- X while (!done) {
- X ch = rawch();
- X switch (ch) {
- X case '\n':
- X case '\r':
- X case ' ':
- X done = 1;
- X break;
- X case '\033':
- X findword();
- X break;
- X case '\177': /* <del> */
- X case '\010': /* <bs> */
- X if (p == q)
- X break;
- X p--;
- X getyx(stdscr, row, col);
- X move(row, col - 1);
- X clrtoeol();
- X refresh();
- X break;
- X case '\025': /* <^u> */
- X case '\027': /* <^w> */
- X if (p == q)
- X break;
- X getyx(stdscr, row, col);
- X move(row, col - (int) (p - q));
- X p = q;
- X clrtoeol();
- X refresh();
- X break;
- X#ifdef SIGTSTP
- X case '\032': /* <^z> */
- X stop_catcher();
- X break;
- X#endif
- X case '\023': /* <^s> */
- X stoptime();
- X printw("<PAUSE>");
- X refresh();
- X while ((ch = inputch()) != '\021' && ch != '\023')
- X ;
- X move(crow, ccol);
- X clrtoeol();
- X refresh();
- X starttime();
- X break;
- X case '\003': /* <^c> */
- X cleanup();
- X exit(0);
- X /*NOTREACHED*/
- X case '\004': /* <^d> */
- X done = 1;
- X ch = EOF;
- X break;
- X case '\014': /* <^l> */
- X case '\022': /* <^r> */
- X clearok(stdscr, 1);
- X refresh();
- X break;
- X case '?':
- X stoptime();
- X if (help() < 0)
- X showstr("Can't open help file", 1);
- X starttime();
- X break;
- X default:
- X if (!islower(ch))
- X break;
- X if ((int) (p - q) == MAXWORDLEN) {
- X p = q;
- X badword();
- X break;
- X }
- X *p++ = ch;
- X addch(ch);
- X refresh();
- X break;
- X }
- X }
- X *p = '\0';
- X if (ch == EOF)
- X return((char *) NULL);
- X return(q);
- X}
- X
- Xinputch()
- X{
- X
- X return(getch() & 0177);
- X}
- X
- X#ifdef XXX
- X/*
- X * Flush all pending input
- X */
- Xflushin(fp)
- XFILE *fp;
- X{
- X
- X flushinp();
- X}
- X#endif XXX
- X
- X#ifdef TIOCFLUSH
- X#include <sys/file.h>
- X
- Xflushin(fp)
- XFILE *fp;
- X{
- X int arg;
- X
- X arg = FREAD;
- X (void) ioctl(fileno(fp), TIOCFLUSH, &arg);
- X}
- X#endif TIOCFLUSH
- X
- X#ifdef ATARI
- X#include <osbind.h>
- X
- X/*ARGSUSED*/
- Xflushin(fp)
- XFILE *fp;
- X{
- X
- X while (Cconis() == -1)
- X ;
- X}
- X#endif ATARI
- X
- Xstatic int gone;
- X
- X/*
- X * Stop the game timer
- X */
- Xstoptime()
- X{
- X long t;
- X extern long start_t;
- X
- X time(&t);
- X gone = (int) (t - start_t);
- X}
- X
- X/*
- X * Restart the game timer
- X */
- Xstarttime()
- X{
- X long t;
- X extern long start_t;
- X
- X time(&t);
- X start_t = t - (long) gone;
- X}
- X
- X/*
- X * Initialize for the display of the player's words as they are typed
- X * This display starts at (LIST_LINE, LIST_COL) and goes "down" until the last
- X * line. After the last line a new column is started at LIST_LINE
- X * Keep track of each column position for showword()
- X * There is no check for exceeding COLS
- X */
- Xstartwords()
- X{
- X
- X crow = LIST_LINE;
- X ccol = LIST_COL;
- X maxw = 0;
- X ncolstarts = 1;
- X colstarts[0] = LIST_COL;
- X move(LIST_LINE, LIST_COL);
- X refresh();
- X}
- X
- X/*
- X * Add a word to the list and start a new column if necessary
- X * The maximum width of the current column is maintained so we know where
- X * to start the next column
- X */
- Xaddword(w)
- Xchar *w;
- X{
- X int n;
- X
- X if (crow == lastline) {
- X crow = LIST_LINE;
- X ccol += (maxw + 5);
- X colstarts[ncolstarts++] = ccol;
- X maxw = 0;
- X move(crow, ccol);
- X }
- X else {
- X move(++crow, ccol);
- X if ((n = strlen(w)) > maxw)
- X maxw = n;
- X }
- X refresh();
- X}
- X
- X/*
- X * The current word is unacceptable so erase it
- X */
- Xbadword()
- X{
- X
- X move(crow, ccol);
- X clrtoeol();
- X refresh();
- X}
- X
- X/*
- X * Highlight the nth word in the list (starting with word 0)
- X * No check for wild arg
- X */
- Xshowword(n)
- Xint n;
- X{
- X int col, row;
- X
- X row = LIST_LINE + n % (lastline - LIST_LINE + 1);
- X col = colstarts[n / (lastline - LIST_LINE + 1)];
- X move(row, col);
- X standout();
- X printw("%s", pword[n]);
- X standend();
- X move(crow, ccol);
- X refresh();
- X sleep(1);
- X move(row, col);
- X printw("%s", pword[n]);
- X move(crow, ccol);
- X refresh();
- X}
- X
- X/*
- X * Get a word from the user and check if it is in either of the two
- X * word lists
- X * If it's found, show the word on the board for a short time and then
- X * erase the word
- X *
- X * Note: this function knows about the format of the board
- X */
- Xfindword()
- X{
- X int c, col, found, i, r, row;
- X char buf[MAXWORDLEN + 1];
- X extern char board[];
- X extern int usedbits, wordpath[];
- X extern char *mword[], *pword[];
- X extern int nmwords, npwords;
- X
- X getyx(stdscr, r, c);
- X getword(buf);
- X found = 0;
- X for (i = 0; i < npwords; i++) {
- X if (strcmp(buf, pword[i]) == 0) {
- X found = 1;
- X break;
- X }
- X }
- X if (!found) {
- X for (i = 0; i < nmwords; i++) {
- X if (strcmp(buf, mword[i]) == 0) {
- X found = 1;
- X break;
- X }
- X }
- X }
- X for (i = 0; i < MAXWORDLEN; i++)
- X wordpath[i] = -1;
- X usedbits = 0;
- X if (!found || checkword(buf, -1, wordpath) == -1) {
- X move(r, c);
- X clrtoeol();
- X addstr("[???]");
- X refresh();
- X sleep(1);
- X move(r, c);
- X clrtoeol();
- X refresh();
- X return;
- X }
- X
- X standout();
- X for (i = 0; wordpath[i] != -1; i++) {
- X row = BOARD_LINE + (wordpath[i] / 4) * 2 + 1;
- X col = BOARD_COL + (wordpath[i] % 4) * 4 + 2;
- X move(row, col);
- X if (board[wordpath[i]] == 'q')
- X printw("Qu");
- X else
- X printw("%c", toupper(board[wordpath[i]]));
- X move(r, c);
- X refresh();
- X sleep(1);
- X }
- X
- X standend();
- X
- X for (i = 0; wordpath[i] != -1; i++) {
- X row = BOARD_LINE + (wordpath[i] / 4) * 2 + 1;
- X col = BOARD_COL + (wordpath[i] % 4) * 4 + 2;
- X move(row, col);
- X if (board[wordpath[i]] == 'q')
- X printw("Qu");
- X else
- X printw("%c", toupper(board[wordpath[i]]));
- X }
- X move(r, c);
- X clrtoeol();
- X refresh();
- X}
- X
- X/*
- X * Display a string at the current cursor position for the given number of secs
- X */
- Xshowstr(str, delay)
- Xchar *str;
- Xint delay;
- X{
- X
- X addstr(str);
- X refresh();
- X sleep(delay);
- X move(crow, ccol);
- X clrtoeol();
- X refresh();
- X}
- X
- Xputstr(s)
- Xchar *s;
- X{
- X
- X addstr(s);
- X}
- X
- X/*
- X * Get a valid word and put it in the buffer
- X */
- Xgetword(q)
- Xchar *q;
- X{
- X int ch, col, done, i, row;
- X char *p;
- X
- X done = 0;
- X i = 0;
- X p = q;
- X addch('[');
- X refresh();
- X while (!done && i < MAXWORDLEN - 1) {
- X ch = getch() & 0177;
- X switch (ch) {
- X case '\177': /* <del> */
- X case '\010': /* <bs> */
- X if (p == q)
- X break;
- X p--;
- X getyx(stdscr, row, col);
- X move(row, col - 1);
- X clrtoeol();
- X break;
- X case '\025': /* <^u> */
- X case '\027': /* <^w> */
- X if (p == q)
- X break;
- X getyx(stdscr, row, col);
- X move(row, col - (int) (p - q));
- X p = q;
- X clrtoeol();
- X break;
- X case ' ':
- X case '\n':
- X case '\r':
- X done = 1;
- X break;
- X case '\014': /* <^l> */
- X case '\022': /* <^r> */
- X clearok(stdscr, 1);
- X refresh();
- X break;
- X default:
- X if (islower(ch)) {
- X *p++ = ch;
- X addch(ch);
- X i++;
- X }
- X break;
- X }
- X refresh();
- X }
- X *p = '\0';
- X addch(']');
- X refresh();
- X}
- X
- Xshowboard(b)
- Xchar *b;
- X{
- X
- X tty_showboard(b);
- X}
- X
- Xprompt(mesg)
- Xchar *mesg;
- X{
- X
- X move(PROMPT_LINE, PROMPT_COL);
- X printw("%s", mesg);
- X move(PROMPT_LINE + 1, PROMPT_COL);
- X refresh();
- X}
- X
- Xrawch()
- X{
- X
- X#ifdef TIMER
- X return(timerch());
- X#else
- X return(getch() & 0177);
- X#endif
- X}
- X
- Xstatic
- Xtty_setup()
- X{
- X#ifdef SIGTSTP
- X int stop_catcher(), cont_catcher();
- X#endif
- X#ifdef TIOCGWINSZ
- X int winch_catcher();
- X#endif
- X
- X initscr();
- X raw();
- X noecho();
- X
- X /*
- X * Does curses look at the winsize structure?
- X * Should handle SIGWINCH ...
- X */
- X nlines = LINES;
- X lastline = nlines - 1;
- X ncols = COLS;
- X
- X#ifdef SIGTSTP
- X (void) signal(SIGTSTP, stop_catcher);
- X (void) signal(SIGCONT, cont_catcher);
- X#endif
- X#ifdef TIOCGWINSZ
- X (void) signal(SIGWINCH, winch_catcher);
- X#endif
- X
- X return(0);
- X}
- X
- X#ifdef SIGTSTP
- Xstatic
- Xstop_catcher()
- X{
- X
- X stoptime();
- X noraw();
- X echo();
- X move(nlines - 1, 0);
- X refresh();
- X
- X (void) signal(SIGTSTP, SIG_DFL);
- X#ifdef BSD42
- X (void) sigsetmask(sigblock(0) & ~(1 << (SIGTSTP-1)));
- X#endif
- X (void) kill(0, SIGTSTP);
- X (void) signal(SIGTSTP, stop_catcher);
- X}
- X
- Xstatic
- Xcont_catcher()
- X{
- X
- X (void) signal(SIGCONT, cont_catcher);
- X noecho();
- X raw();
- X clearok(stdscr, 1);
- X move(crow, ccol);
- X refresh();
- X starttime();
- X}
- X#endif SIGTSTP
- X
- X#ifdef SIGWINCH
- X/*
- X * The signal is caught but nothing is done about it...
- X * It would mean reformatting the entire display
- X */
- Xstatic
- Xwinch_catcher()
- X{
- X
- X struct winsize win;
- X
- X (void) signal(SIGWINCH, winch_catcher);
- X (void) ioctl(fileno(stdout), TIOCGWINSZ, &win);
- X /*
- X LINES = win.ws_row;
- X COLS = win.ws_col;
- X */
- X}
- X#endif
- X
- Xstatic
- Xtty_cleanup()
- X{
- X
- X move(nlines - 1, 0);
- X refresh();
- X noraw();
- X echo();
- X endwin();
- X}
- X
- Xstatic
- Xtty_showboard(b)
- Xchar *b;
- X{
- X register int i;
- X int line;
- X
- X clear();
- X move(BOARD_LINE, BOARD_COL);
- X line = BOARD_LINE;
- X printw("+---+---+---+---+");
- X move(++line, BOARD_COL);
- X for (i = 0; i < 16; i++) {
- X if (b[i] == 'q')
- X printw("| Qu");
- X else
- X printw("| %c ", toupper(b[i]));
- X if ((i + 1) % 4 == 0) {
- X printw("|");
- X move(++line, BOARD_COL);
- X printw("+---+---+---+---+");
- X move(++line, BOARD_COL);
- X }
- X }
- X move(SCORE_LINE, SCORE_COL);
- X printw("Type '?' for help");
- X refresh();
- X}
- X
- Xstatic
- Xtty_prompt(p)
- Xchar *p;
- X{
- X
- X move(PROMPT_LINE, PROMPT_COL);
- X printw("%s", p);
- X clrtoeol();
- X refresh();
- X}
- X
- END_OF_mach.c
- if test 10502 -ne `wc -c <mach.c`; then
- echo shar: \"mach.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f mkdict.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"mkdict.c\"
- else
- echo shar: Extracting \"mkdict.c\" \(1207 characters\)
- sed "s/^X//" >mkdict.c <<'END_OF_mkdict.c'
- X/* vi: set tabstop=4 : */
- X
- X/*
- X * Filter out words that:
- X * 1) Are not completely made up of lower case letters
- X * 2) Contain a 'q' not immediately followed by a 'u'
- X * 3) Are less that 3 characters long
- X * 4) Are greater than MAXWORDLEN characters long
- X */
- X
- X#include <ctype.h>
- X#include <stdio.h>
- X
- X#include "bog.h"
- X
- Xmain(argc, argv)
- Xint argc;
- Xchar **argv;
- X{
- X register char *p, *q, *r;
- X register int ch, common, i, n;
- X int current, len, prev, qcount;
- X char buf[2][MAXWORDLEN + 1];
- X
- X prev = 0;
- X current = 1;
- X buf[prev][0] = '\0';
- X if (argc == 2)
- X n = atoi(argv[1]);
- X i = 1;
- X while (gets(buf[current]) != (char *) NULL) {
- X if (argc == 2 && i++ % n)
- X continue;
- X len = 0;
- X for (p = buf[current]; *p != '\0'; p++) {
- X if (!islower(*p))
- X break;
- X if (*p == 'q') {
- X q = p + 1;
- X if (*q != 'u')
- X break;
- X else {
- X while (*q = *(q + 1))
- X q++;
- X }
- X len++;
- X }
- X len++;
- X }
- X if (*p != '\0' || len < 3 || len > MAXWORDLEN)
- X continue;
- X
- X p = buf[current];
- X q = buf[prev];
- X qcount = 0;
- X while ((ch = *p++) == *q++ && ch != '\0')
- X if (ch == 'q')
- X qcount++;
- X common = p - buf[current] - 1;
- X printf("%c%s", common + qcount, p - 1);
- X prev = !prev;
- X current = !current;
- X }
- X}
- X
- END_OF_mkdict.c
- if test 1207 -ne `wc -c <mkdict.c`; then
- echo shar: \"mkdict.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f mkindex.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"mkindex.c\"
- else
- echo shar: Extracting \"mkindex.c\" \(1377 characters\)
- sed "s/^X//" >mkindex.c <<'END_OF_mkindex.c'
- X/* vi: set tabstop=4 : */
- X
- X#include <stdio.h>
- X
- X#include "bog.h"
- X
- Xmain(argc, argv)
- Xint argc;
- Xchar **argv;
- X{
- X int clen, rlen, prev;
- X long off, start;
- X char buf[MAXWORDLEN + 1], *p, *nextword();
- X
- X prev = '\0';
- X off = start = 0L;
- X while (nextword(stdin, buf, &clen, &rlen) != (char *) NULL) {
- X if (*buf != prev) {
- X if (prev != '\0')
- X printf("%c %6ld %6ld\n", prev, start, off - 1);
- X prev = *buf;
- X start = off;
- X }
- X off += clen + 1;
- X }
- X printf("%c %6ld %6ld\n", prev, start, off - 1);
- X}
- X
- X/*
- X * Return the next word in the compressed dictionary in 'buffer' or
- X * NULL on end-of-file
- X * Also set clen to the length of the compressed word (for mkindex) and
- X * rlen to the strlen() of the real word
- X */
- Xchar *
- Xnextword(fp, buffer, clen, rlen)
- XFILE *fp;
- Xchar *buffer;
- Xint *clen, *rlen;
- X{
- X register int ch, pcount;
- X register char *p, *q;
- X static char buf[MAXWORDLEN + 1];
- X static int first = 1;
- X static int lastch = 0;
- X
- X if (first) {
- X if ((pcount = getc(fp)) == EOF)
- X return((char *) NULL);
- X first = 0;
- X }
- X else if ((pcount = lastch) == EOF)
- X return((char *) NULL);
- X
- X p = buf + (*clen = pcount);
- X
- X while ((ch = getc(fp)) != EOF && ch >= 'a')
- X *p++ = ch;
- X lastch = ch;
- X *p = '\0';
- X
- X *rlen = (int) (p - buf);
- X *clen = *rlen - *clen;
- X
- X p = buf;
- X q = buffer;
- X while ((*q++ = *p) != '\0') {
- X if (*p++ == 'q')
- X *q++ = 'u';
- X }
- X return(buffer);
- X}
- X
- END_OF_mkindex.c
- if test 1377 -ne `wc -c <mkindex.c`; then
- echo shar: \"mkindex.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f prtable.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"prtable.c\"
- else
- echo shar: Extracting \"prtable.c\" \(2164 characters\)
- sed "s/^X//" >prtable.c <<'END_OF_prtable.c'
- X/* vi: set tabstop=4 : */
- X
- X#include <curses.h>
- X
- X#define NCOLS 5
- X
- X/*
- X * Routine to print a table
- X * Modified from 'ls.c' mods (BJB/83)
- X * Arguments:
- X * base - address of first entry
- X * num - number of entries
- X * d_cols - number of columns to use if > 0, "best" size if == 0
- X * width - max line width if not zero
- X * prentry - address of the routine to call to print the string
- X * length - address of the routine to call to determine the length
- X * of string to be printed
- X *
- X * prtable and length are called with the the address of the base and
- X * an index
- X */
- Xprtable(base, num, d_cols, width, prentry, length)
- Xchar *base;
- Xint num, d_cols;
- Xint (*prentry)(), (*length)();
- X{
- X register int c, j;
- X register int a, b, cols, loc, maxlen, nrows, z;
- X int col, row;
- X
- X if (num == 0)
- X return;
- X maxlen = get_maxlen(base, num, length) + 1;
- X if (d_cols > 0)
- X cols = d_cols;
- X else
- X cols = width / maxlen;
- X if (cols == 0)
- X cols = NCOLS;
- X nrows = (num - 1) / cols + 1;
- X for (a = 1; a <= nrows; a++) {
- X b = c = z = loc = 0;
- X for (j = 0; j < num; j++) {
- X c++;
- X if (c >= a + b)
- X break;
- X }
- X while (j < num) {
- X (*prentry)(base, j);
- X loc += (*length)(base, j);
- X z++;
- X b += nrows;
- X for (j++; j < num; j++) {
- X c++;
- X if (c >= a + b)
- X break;
- X }
- X if (j < num) {
- X while (loc < z * maxlen) {
- X addch(' ');
- X loc++;
- X }
- X }
- X }
- X getyx(stdscr, row, col);
- X move(row + 1, 0);
- X }
- X refresh();
- X}
- X
- Xstatic int
- Xget_maxlen(base, num, length)
- Xchar *base;
- Xint num;
- Xint (*length)();
- X{
- X register int i, len, max;
- X
- X max = (*length)(base, 0);
- X for (i = 0; i < num; i++) {
- X if ((len = (*length)(base, i)) > max)
- X max = len;
- X }
- X return(max);
- X}
- X
- END_OF_prtable.c
- if test 2164 -ne `wc -c <prtable.c`; then
- echo shar: \"prtable.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f showdict.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"showdict.c\"
- else
- echo shar: Extracting \"showdict.c\" \(264 characters\)
- sed "s/^X//" >showdict.c <<'END_OF_showdict.c'
- X/* vi: set tabstop=4 : */
- X
- X#include <stdio.h>
- X
- X#include "bog.h"
- X
- X/*BOGUS*/
- Xstruct dictindex dictindex[1];
- Xint wordlen;
- X
- Xmain(argc, argv)
- Xint argc;
- Xchar **argv;
- X{
- X char *p;
- X char *nextword();
- X
- X while ((p = nextword(stdin)) != (char *) NULL)
- X printf("%s\n", p);
- X}
- X
- END_OF_showdict.c
- if test 264 -ne `wc -c <showdict.c`; then
- echo shar: \"showdict.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f timer.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"timer.c\"
- else
- echo shar: Extracting \"timer.c\" \(1799 characters\)
- sed "s/^X//" >timer.c <<'END_OF_timer.c'
- X/* vi: set tabstop=4 : */
- X
- X#include "bog.h"
- X
- X#ifdef TIMER
- X
- X#include <setjmp.h>
- X#include <curses.h>
- X#include <stdio.h>
- X
- X/*
- X * Update the display of the remaining time while waiting for a character
- X * If time runs out do a longjmp() to the game controlling routine, returning
- X * non-zero; oth. return the character
- X * Leave the cursor where it was initially
- X */
- Xtimerch()
- X{
- X int col, remaining, row;
- X long prevt, t;
- X extern int tlimit;
- X extern long start_t;
- X extern jmp_buf env;
- X
- X getyx(stdscr, row, col);
- X prevt = 0L;
- X while (1) {
- X if (waitch(1000L) == 1)
- X break;
- X time(&t);
- X if (t == prevt)
- X continue;
- X prevt = t;
- X remaining = tlimit - (int) (t - start_t);
- X if (remaining < 0) {
- X longjmp(env, 1);
- X /*NOTREACHED*/
- X }
- X move(TIMER_LINE, TIMER_COL);
- X printw("%d:%02d", remaining / 60, remaining % 60);
- X move(row, col);
- X refresh();
- X }
- X return(getch() & 0177);
- X}
- X
- X/*
- X * Wait up to 'delay' microseconds for input to appear
- X * Returns 1 if input is ready, 0 oth.
- X */
- X
- X#ifdef BSD42
- X
- X#include <sys/time.h>
- X
- Xstatic
- Xwaitch(delay)
- Xlong delay;
- X{
- X int fdbits;
- X struct timeval duration;
- X
- X duration.tv_sec = 0L;
- X duration.tv_usec = delay;
- X fdbits = 1;
- X return(select(32, &fdbits, 0, 0, &duration));
- X}
- X#endif BSD42
- X
- X#ifdef SYSV
- X
- X#include <sys/ioctl.h>
- X
- X/*
- X * This is not too efficient...
- X */
- Xstatic
- Xwaitch(delay)
- Xlong delay;
- X{
- X int nchars;
- X
- X if (ioctl(fileno(stdin), FIONREAD, &nchars) < 0) {
- X perror("ioctl():");
- X cleanup();
- X exit(1);
- X }
- X return(nchars > 0);
- X}
- X#endif SYSV
- X
- X#ifdef ATARI
- X
- X#include <osbind.h>
- X
- X/*
- X * The ST curses turns on the cursor only when a read is performed
- X * Since there's nothing better to do at this point the cursor can
- X * be enabled
- X */
- Xstatic
- Xwaitch(delay)
- Xlong delay;
- X{
- X
- X Bconout(2, '\033');
- X Bconout(2, 'e');
- X return(Cconis() == -1);
- X}
- X#endif ATARI
- X
- X#endif TIMER
- X
- END_OF_timer.c
- if test 1799 -ne `wc -c <timer.c`; then
- echo shar: \"timer.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f word.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"word.c\"
- else
- echo shar: Extracting \"word.c\" \(3450 characters\)
- sed "s/^X//" >word.c <<'END_OF_word.c'
- X/* vi: set tabstop=4 : */
- X
- X#include <stdio.h>
- X
- X#include "bog.h"
- X
- X#ifdef ATARI
- X#include <stat.h>
- X#include <osbind.h>
- X#define malloc(x) Malloc(x)
- X#else
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#endif
- X
- Xstatic char *dictspace, *dictend;
- Xstatic char *sp;
- X
- Xstatic int first = 1, lastch = 0;
- X
- X/*
- X * Return the next word in the compressed dictionary in 'buffer' or
- X * NULL on end-of-file
- X */
- Xchar *
- Xnextword(fp)
- XFILE *fp;
- X{
- X register int ch, pcount;
- X register char *p;
- X static char buf[MAXWORDLEN + 1];
- X extern int wordlen;
- X
- X if (fp == (FILE *) NULL) {
- X if (sp == dictend)
- X return((char *) NULL);
- X
- X p = buf + (int) *sp++;
- X
- X /*
- X * The dictionary ends with a null byte
- X */
- X while (*sp >= 'a') {
- X if ((*p++ = *sp++) == 'q')
- X *p++ = 'u';
- X }
- X }
- X else {
- X if (first) {
- X if ((pcount = getc(fp)) == EOF)
- X return((char *) NULL);
- X first = 0;
- X }
- X else if ((pcount = lastch) == EOF)
- X return((char *) NULL);
- X
- X p = buf + pcount;
- X
- X while ((ch = getc(fp)) != EOF && ch >= 'a') {
- X if ((*p++ = ch) == 'q')
- X *p++ = 'u';
- X }
- X lastch = ch;
- X }
- X wordlen = (int) (p - buf);
- X *p = '\0';
- X return(buf);
- X}
- X
- X/*
- X * Reset the state of nextword() and do the fseek()
- X */
- Xdictseek(fp, offset, ptrname)
- XFILE *fp;
- Xlong offset;
- Xint ptrname;
- X{
- X
- X if (fp == (FILE *) NULL) {
- X if ((sp = dictspace + offset) >= dictend)
- X return(-1);
- X return(0);
- X }
- X
- X first = 1;
- X return(fseek(fp, offset, ptrname));
- X}
- X
- XFILE *
- Xopendict(dict)
- Xchar *dict;
- X{
- X FILE *fp;
- X
- X#ifdef ATARI
- X if ((fp = fopen(dict, "rb")) == (FILE *) NULL)
- X return((FILE *) NULL);
- X#else
- X if ((fp = fopen(dict, "r")) == (FILE *) NULL)
- X return((FILE *) NULL);
- X#endif
- X return(fp);
- X}
- X
- X/*
- X * Load the given dictionary and initialize the pointers
- X */
- Xloaddict(fp)
- XFILE *fp;
- X{
- X int st;
- X char *p;
- X long n;
- X struct stat statb;
- X
- X#ifdef ATARI
- X if (stat(DICT, &statb) < 0) {
- X (void) fclose(fp);
- X return(-1);
- X }
- X#else
- X char *malloc();
- X
- X if (fstat(fileno(fp), &statb) < 0) {
- X (void) fclose(fp);
- X return(-1);
- X }
- X#endif
- X
- X /*
- X * An extra character (a sentinel) is allocated and set to null to improve
- X * the expansion loop in nextword()
- X */
- X if ((dictspace = (char *) malloc(statb.st_size + 1)) == (char *) NULL) {
- X (void) fclose(fp);
- X return(-1);
- X }
- X n = (long) statb.st_size;
- X sp = dictspace;
- X dictend = dictspace + n;
- X
- X p = dictspace;
- X while (n > 0 && (st = fread(p, 1, BUFSIZ, fp)) > 0) {
- X p += st;
- X n -= st;
- X }
- X if (st < 0) {
- X (void) fclose(fp);
- X (void) fprintf(stderr, "Error reading dictionary\n");
- X return(-1);
- X }
- X *p = '\0';
- X return(0);
- X}
- X
- X/*
- X * Dependent on the exact format of the index file:
- X * Starting offset field begins in column 1 and length field in column 9
- X */
- Xloadindex(indexfile)
- Xchar *indexfile;
- X{
- X register int i, j;
- X char buf[MAXWORDLEN + 1];
- X FILE *fp;
- X long atol();
- X extern struct dictindex dictindex[];
- X
- X if ((fp = fopen(indexfile, "r")) == (FILE *) NULL) {
- X (void) fprintf(stderr, "Can't open '%s'\n", indexfile);
- X return(-1);
- X }
- X i = 0;
- X while (fgets(buf, sizeof(buf), fp) != (char *) NULL) {
- X j = *buf - 'a';
- X if (i != j) {
- X (void) fprintf(stderr, "Bad index order\n");
- X return(-1);
- X }
- X dictindex[j].start = atol(buf + 1);
- X dictindex[j].length = atol(buf + 9) - dictindex[j].start;
- X i++;
- X }
- X if (i != 26) {
- X (void) fprintf(stderr, "Bad index length\n");
- X return(-1);
- X }
- X (void) fclose(fp);
- X return(0);
- X}
- X
- END_OF_word.c
- if test 3450 -ne `wc -c <word.c`; then
- echo shar: \"word.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f helpfile -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"helpfile\"
- else
- echo shar: Extracting \"helpfile\" \(3620 characters\)
- sed "s/^X//" >helpfile <<'END_OF_helpfile'
- X
- XCommands:
- X
- XEnter word: <return> or <linefeed> or <space>
- XDelete previous character: <delete> or <backspace>
- XDelete line: <^u> or <^w>
- XRedraw screen: <^l> or <^r>
- XPause game: <^s>
- XResume game: <^q> or <^s>
- XSuspend game (BSD only): <^z>
- XGive up on current cube: <^d>
- XShow remaining time: <space> first thing on a line
- XShow help: ? (Suspends timer until done)
- XExit game: <^c>
- X
- X(^u means "control u", etc.)
- X
- X[Note for users of versions of this program that do not display a timer:
- XThe first word entered after the timer has run out causes a list of all the
- Xwords you found, the words you missed, and your running statistics to be
- Xdisplayed.]
- X
- XAny time you are prompted while the board is displayed you can type:
- X <esc>word
- Xto see where "word" is on the board.
- X
- XUsage:
- X bog [-b] [-d] [-s#] [-t#] [-w#] [+[+]] [boardspec]
- X
- X -b: batch mode (boardspec must be present); dictionary read from stdin
- X -d: debug mode
- X -s#: use # as the random number seed
- X -t#: time limit is # seconds instead of default 180
- X -w#: minimum word length is # letters instead of default 3
- X +: can reuse a cube, but not twice in succession
- X ++: can reuse cubes arbitrarily
- X boardspec: the first board to use (use 'q' for 'qu'); e.g.:
- X bog nolezeebnqieegei
- X.
- X Default Rules
- X
- XA Boggle board is a four by four arrangement of Boggle cubes.
- XYou have 3 minutes to find as many words as possible in the Boggle board.
- XWords are formed by finding a sequence of cubes (letters) that are in the
- Xgame's dictionary. The (N+1)th cube in the word must be horizontally,
- Xvertically, or diagonally adjacent to the Nth cube. Cubes cannot be reused.
- XWords consist solely of lower case letters and must be at least 3 letters long.
- X.
- X Options
- X
- XCommand line flags can be given to change the rules of the game.
- XThe '+' flag allows a cube to be used multiple times, but not in succession.
- XThe '++' flag allows the same cubes to be considered adjacent to itself.
- XThe time limit can be changed from the default 3 minutes by using the flag
- X'-t#', where # is the duration (in seconds) of each game.
- XThe minimum word length can be changed from 3 letters by specifying 'w#',
- Xwhere # is the minimum number of letters to use.
- X.
- X Bugs and Limitations
- X
- XThe following bugs and problems are known to exist:
- X
- X- If there are a great many words in the cube the final display of the words
- X may scroll off of the screen. (On a 25 line screen about 130 words can be
- X displayed.)
- X
- X- Computing the complete word list can be too slow on small machines.
- X
- X- No word can contain a 'q' that is not immediately followed by a 'u'.
- X
- X- When using the '+' or '++' options the display of words found in the board
- X doesn't indicate reused cubes.
- X.
- X About This Program
- X
- XPermission is given to freely copy and distribute this software providing:
- X
- X1) You do not sell it,
- X2) You do not use it for commercial advantage,
- X3) If you pass the program on you must make the source code available, and
- X4) This notice must accompany the distribution
- X
- XPlease notify the author of any bugs or if you have any suggestions.
- X
- XCopyright (c) 1988:
- XBarry Brachman
- XDept. of Computer Science
- XUniv. of British Columbia
- XVancouver, B.C. V6T 1W5
- X
- X.. {ihnp4!alberta, uw-beaver, uunet}!ubc-vision!ubc-csgrads!brachman
- Xbrachman@grads.cs.ubc.cdn
- Xbrachman%ubc.csnet@csnet-relay.arpa
- Xbrachman@ubc.csnet
- X
- XBoggle is a trademark of Parker Brothers.
- X
- END_OF_helpfile
- if test 3620 -ne `wc -c <helpfile`; then
- echo shar: \"helpfile\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- echo shar: End of shell archive.
- exit 0
-